package cn.krui.helper.pub_sub;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import cn.krui.helper.bean.PublisterBean;
import cn.krui.helper.tools.JsonUtils;
import cn.krui.helper.tools.RedisUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @author zc
 * 向redis推送消息通知，通知的消息会被保存到redis的队列
 */
public class Publisher {
    private static final Logger logger = LoggerFactory.getLogger(Publisher.class);
    private String spring_redis_host;
    private int spring_redis_port;
    private int spring_redis_timeout;
    private String spring_redis_password;
    private JedisPool jedisPool;
    private Jedis jedis;
    private StringRedisTemplate redisTemplate;
    private String prefix;

    public Publisher(String spring_redis_host, int spring_redis_port, int spring_redis_timeout,
            String spring_redis_password,StringRedisTemplate redisTemplate,String _prefix) {
        this.spring_redis_host = spring_redis_host;
        this.spring_redis_port = spring_redis_port;
        this.spring_redis_timeout = spring_redis_timeout;
        this.spring_redis_password = spring_redis_password;
        this.redisTemplate = redisTemplate;
        this.prefix = _prefix;
    }

    /**
     * redis消息发布
     * 消息会存入pub:{channel}:{message.type}_list队列中，消费端会调用消费方法while(!读到下一个)
     * channel: 频道
     * message：内容
     * @return: 消息发布情况成功
     */
    public boolean pub(String channel, PublisterBean<?> message) {
        // logger.info(String.format("spring_redis_host:%s", spring_redis_host));
        // logger.info(String.format("spring_redis_port:%s", spring_redis_port));
        // logger.info(String.format("spring_redis_timeout:%s", spring_redis_timeout));
        // logger.info(String.format("spring_redis_password:%s", spring_redis_password));
        if(StringUtils.isEmpty(channel) || StringUtils.isEmpty(message.getType())){
            return false;
        }
        try {
            if (StringUtils.isEmpty(spring_redis_password)) {
                this.jedisPool = new JedisPool(new JedisPoolConfig(), spring_redis_host, spring_redis_port,
                        spring_redis_timeout);
            } else {
                this.jedisPool = new JedisPool(new JedisPoolConfig(), spring_redis_host, spring_redis_port,
                        spring_redis_timeout, spring_redis_password);
            } 
            logger.info(String.format("频道%s推送消息：%s", channel, JsonUtils.toJson(message)));
            RedisUtils redisUtils = new RedisUtils(redisTemplate,prefix);
            //zc 0307去掉pub时消息记录
            // redisUtils.lRightPush(String.format("pub:%s:%s_list", channel, message.getType()),
            //         JsonUtils.toJson(message.getData()));
            if (!redisUtils.sIsMember("pub:pub_set", channel)) {
                redisUtils.sAdd("pub:pub_set", new String[] { channel });
            }
            if (!redisUtils.sIsMember(String.format("pub:%s_set", channel), message.getType())) {
                redisUtils.sAdd(String.format("pub:%s_set", channel), new String[] { message.getType() });
            }
            if (!StringUtils.isEmpty(message.getExecUrl()) && !redisUtils.sIsMember(String.format("pub:%s:%s_set", channel, message.getType()),
                    message.getExecUrl())) {
                redisUtils.sAdd(String.format("pub:%s:%s_set", channel, message.getType()), message.getExecUrl());
            }
            
            jedis = jedisPool.getResource(); // 连接池中取出一个连接
            jedis.publish(channel, JsonUtils.toJson(message)); // 从频道上推送消息
            
            jedisPool.close();
            jedis.close();
        } catch (Exception e) {
            logger.error(String.format("%s", e));
            if (jedisPool != null){
                jedisPool.close();
            }
            if (jedis != null){
                jedis.close();
            }
            return false;
        }
        return true;
    }

}